/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package GUI;

import MouseSensorDriver.Calibrator;
import MouseSensorDriver.MouseSensorHost;
import MouseSensorDriver.MouseSensorListener;
import adc_lcard.ADCE140Driver;
import dynamixel.Actuator;
import java.io.Serializable;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Asko
 */
public class ControlChannel  implements Serializable{

    boolean reverseADC = false;
    boolean reverseMouse = false;
    int mouseSensorNum = 0;
    boolean mouseSensorX = false;
    String channelName = "";
    String measureName;
    MouseSensorHost sensorHost;
    int sensorNum;
    Actuator posActuator;
    int mouseCalibChannel;
    int adcChannel;
    int calibrChannel;
    int ADC_MAX = 65530;
    int ADC_MIN = 1;
    int mousePos = 0;
    long res = 0;
    final int filterValue = 1;
    int[] values = new int[filterValue];
    int filtrCursor = 0;
    transient MouseSensorListener ml = new MouseSensorListener() {
        @Override
        public void measured(int dx1, int dy1, int dx2, int dy2,
                int dx3, int dy3) {
//            if (reverseMouse) {
//                dx1 = -dx1;
//                dx2 = -dx2;
//                dx3 = -dx3;
//                dy1 = -dy1;
//                dy2 = -dy2;
//                dy3 = -dy3;
//            }
            switch (mouseCalibChannel) {
                case 0: {
                    mousePos += dx1;
                    break;
                }
                case 1: {
                    mousePos += dy1;
                    break;
                }
                case 2: {
                    mousePos += dx2;
                    break;
                }
                case 3: {
                    mousePos += dy2;
                    break;
                }
                case 4: {
                    mousePos += dx3;
                    break;
                }
                case 5: {
                    mousePos += dy3;
                    break;
                }
            }
        }
    };

    public ControlChannel(String name, MouseSensorHost sensorHost,
            Actuator posActuator, int adc_channel, int calibrChannel,
            int mouseCalibChannel, String measureName,boolean amouseSensorX,int 
                    mouseSensorNum) {
        this.channelName = name;
        this.sensorHost = sensorHost;
        this.posActuator = posActuator;
        this.adcChannel = adc_channel;
        this.calibrChannel = calibrChannel;
        this.mouseCalibChannel = mouseCalibChannel;
        this.measureName = measureName;
        //  startMouseReg();
        this.mouseSensorX = amouseSensorX;
        this.mouseSensorNum = mouseSensorNum ;
        System.out.println("Mouse num " + mouseSensorNum + " mouse X"
                + mouseSensorX);
        for (int i = 0; i < filterValue; i++) {
            getSourcePos();
        }
    }

    public ControlChannel(String name, MouseSensorHost sensorHost,
            Actuator posActuator, int adc_channel, int calibrChannel,
            int mouseChannel, String measureName, boolean amouseSensorX,int 
                    mouseSensorNum,boolean reverseADC,
            boolean reverseMouse) {
        this(name, sensorHost, posActuator, adc_channel,
                calibrChannel, mouseChannel, measureName,amouseSensorX,
                mouseSensorNum);
        this.reverseADC = reverseADC;
        this.reverseMouse = reverseMouse;

    }

    public void goToPosition(double pos, int inputSpeed) {
        final double rs = pos;
        final int speed = inputSpeed;
        int sdata = Calibrator.get().getSourceData(calibrChannel, rs);
        if (sdata < ADC_MAX && sdata > ADC_MIN) {
            Thread controlThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    boolean clockWise = false;
                    if (reverseADC) {
                        clockWise = true;
                    }
                    // posExecButton.setEnabled(false);
                    posActuator.turnOnLed(true);
                    double curPos = getCurPos();
                    if (((rs < curPos && Calibrator.get().getCoefsProp(calibrChannel) > 0)
                            || (rs > curPos && Calibrator.get().getCoefsProp(calibrChannel) < 0))) {
                        clockWise = true;
                        if (reverseADC) {
                            clockWise = false;
                        }
                    }
                    posActuator.setSpeed(speed, clockWise);
                    if (rs > curPos) {
                        while (rs > getCurPos()) {
                            try {
                                Thread.sleep(20);
                            } catch (InterruptedException ex) {
                                Logger.getLogger(StartFrame.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        }
                    } else {
                        while (rs < getCurPos()) {
                            try {
                                Thread.sleep(20);
                            } catch (InterruptedException ex) {
                                Logger.getLogger(StartFrame.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        }
                    }
                    posActuator.setSpeed(0, false);
                    posActuator.turnOnLed(false);
                    // posExecButton.setEnabled(true);
                }
            });
            controlThread.start();
            try {
                controlThread.join();

                /* while (controlThread.isAlive()) {
                 try {
                 controlThread.join(100);
                 } catch (InterruptedException ex) {
                 Logger.getLogger(ControlChannel.class.getName()).log(Level.SEVERE, null, ex);
                 }
                 }*/
            } catch (InterruptedException ex) {
                Logger.getLogger(ControlChannel.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

    }

    public String getChannelName() {
        return channelName;
    }

    public double getCurPos() {
        return Calibrator.get().getData(calibrChannel,
                getSourcePos());
    }

    public long getSourcePos() {
        res -= values[filtrCursor];
        values[filtrCursor] = ADCE140Driver.getData(adcChannel);
        res += values[filtrCursor];
        filtrCursor++;
        if (filtrCursor >= filterValue) {
            filtrCursor = 0;
        }
        return res / filterValue;
    }

    public double getCurPos(long sourcePos) {
        return Calibrator.get().getData(calibrChannel, sourcePos);
    }

    @Override
    public String toString() {
        return channelName;
    }

    public void startMouseReg() {
        mousePos = 0;
        sensorHost.addMouseSensorListener(ml);
    }

    public void endMouseReg() {
        sensorHost.removeMouseSensorListener(ml);
    }

    public int getSourceMousePos() {

        if (mouseSensorX) {
            return reverseMouse ? -sensorHost.getX(mouseSensorNum)
                    : sensorHost.getX(mouseSensorNum);
        } else {
            return reverseMouse ? -sensorHost.getY(mouseSensorNum)
                    : sensorHost.getY(mouseSensorNum);
        }
    }

    public double getMousePos() {
        return Calibrator.get().getData(mouseCalibChannel, getSourceMousePos());
    }

    public String getMeasureName() {
        return measureName;
    }
    
    public int getADCChannel(){
        return this.adcChannel ;
    }   
    
    public int getCalibChannel(){
        return this.calibrChannel;
    }

    public int getMouseChannel() {
        return mouseCalibChannel;
    }

    public boolean isMouseSensorX() {
        return mouseSensorX;
    }

    public Actuator getActuator() {
        return posActuator;
    }
}
